Skip to main content

--

Logrotate

Overview

logrotate is a system utility that rotates, compresses, and prunes log files based on rules (size, age, count). It prevents logs from consuming disk space while keeping a retention window for troubleshooting and auditing. On most Linux distributions it is run automatically via cron or systemd timers, applying policies from /etc/logrotate.conf and /etc/logrotate.d/.

History

  • As Unix/Linux systems standardized on file-based logging, log rotation emerged to keep long-running servers stable by controlling log growth.
  • logrotate became the common Linux solution by supporting flexible policies, post-rotate actions, and integration with service reload signals.

Adoption

logrotate is commonly used in:

  • Traditional Linux servers using file-based logs (syslog, application logs, web server logs)
  • VPS and bare-metal deployments where disk space must be managed locally
  • Container hosts and K8s nodes where host logs still need rotation (even if apps use structured logging elsewhere)

Maintainer

Maintained by the Linux distribution and logrotate project/community (packaged and patched by distros).

Best when to use

  • Logs are written to files and you need predictable retention and disk usage control
  • You need compressed historical logs for a defined period
  • You must run post-rotation actions (signal a daemon, reload a service, run scripts)

Not suitable when

  • Logs are exclusively shipped to centralized storage and local files are not used
  • Your application uses log output only to stdout/stderr inside containers with no file logs
  • You need real-time streaming log management rather than periodic rotation

Compatibility notes

  • Rotation scheduling differs:

    • Cron-based systems commonly run daily via /etc/cron.daily/logrotate.
    • Systemd-based systems often use logrotate.timer.
  • Service integration differs: some daemons support copytruncate, others require a signal or reload after rotation.

  • Journald logs are not rotated by logrotate; they are managed by journalctl and journald settings.

Data loss risk

Using copytruncate can lose log lines under heavy write load. Prefer a proper reopen mechanism (signal/reload) when the application supports it.

How it works

logrotate applies rules to a set of log files:

  1. Decide if a log needs rotation (time-based or size-based)
  2. Rename the current log (for example, app.logapp.log.1)
  3. Optionally compress rotated logs
  4. Create a fresh log file with the correct owner/permissions (if configured)
  5. Run post-rotation actions (signal/reload services)
  6. Delete logs beyond retention

Installation

Verify (read-only)

logrotate --version

Install

sudo apt update
sudo apt install logrotate

Configuration locations

LocationPurpose
/etc/logrotate.confGlobal defaults and includes
/etc/logrotate.d/Per-service rotation rules
/var/lib/logrotate/statusRotation state tracking (last run timestamps)

View current global config (read-only):

sudo sed -n '1,200p' /etc/logrotate.conf

List per-service rules:

sudo ls -la /etc/logrotate.d/

Common directives

DirectiveMeaningExample
---
daily / weekly / monthlyRotate by timeweekly
sizeRotate when log exceeds sizesize 100M
rotate NKeep N rotationsrotate 14
compressCompress rotated logscompress
delaycompressCompress from the second rotation onwarddelaycompress
missingokSkip if log missingmissingok
notifemptyDon’t rotate empty logsnotifempty
create MODE OWNER GROUPCreate new log with permscreate 0640 www-data adm
su USER GROUPRotate using that user/groupsu root adm
dateextAppend date to rotated filesdateext
dateformatCustomize date suffixdateformat -%Y%m%d
copytruncateCopy then truncate originalcopytruncate
sharedscriptsRun scripts once per blocksharedscripts
postrotate / endscriptHook after rotatepostrotate ... endscript
Time-based vs size-based

Time-based rotation relies on a periodic scheduler (cron/timer). Size-based rotation still needs periodic execution to notice that the size threshold has been crossed.

Practical configuration examples

Rotate an application log daily, keep 14 days, compress

Create /etc/logrotate.d/myapp:

/var/log/myapp/myapp.log {
daily
rotate 14
missingok
notifempty
compress
delaycompress
create 0640 myapp adm
}

Test (dry run):

sudo logrotate -d /etc/logrotate.d/myapp

Force rotation (use carefully):

sudo logrotate -f /etc/logrotate.d/myapp
Forced rotation

-f ignores normal rotation checks and can rotate even when unnecessary. Use only for validation or when you understand the retention impact.

Rotate NGINX or OpenLiteSpeed logs with reload signaling

Many daemons can reopen logs on reload, which avoids copytruncate.

Example pattern:

/var/log/nginx/*.log {
daily
rotate 7
missingok
notifempty
compress
delaycompress
sharedscripts
postrotate
systemctl reload nginx >/dev/null 2>&1 || true
endscript
}

For OpenLiteSpeed, prefer its supported reload mechanism in postrotate if the logs are not reopening correctly; validate by checking that the new log file receives writes immediately after rotation.

Running and testing

Dry run (debug)

sudo logrotate -d /etc/logrotate.conf

Verbose run

sudo logrotate -v /etc/logrotate.conf

Force run (apply now)

sudo logrotate -f /etc/logrotate.conf

Check last rotation state

sudo tail -n 50 /var/lib/logrotate/status

Check scheduling

Cron

ls -la /etc/cron.daily/ | grep -i logrotate || true

systemd timer

systemctl list-timers | grep -i logrotate || true
systemctl status logrotate.timer 2>/dev/null || true

Troubleshooting

“Permission denied” rotating logs

Common causes:

  • Log files owned by an app user, but rotation runs as root without su
  • Incorrect create owner/group
  • Directory permissions prevent creating new logs

Fix pattern:

  • Add su USER GROUP inside the block.
  • Ensure create MODE OWNER GROUP matches the service.

Example:

/var/log/myapp/myapp.log {
su myapp adm
create 0640 myapp adm
daily
rotate 14
missingok
notifempty
compress
}

Application keeps writing to the old rotated file

Cause: the application did not reopen the log file.

Fix options:

  • Prefer postrotate to send a reload/signal so the app reopens logs.
  • Use copytruncate only if the application cannot reopen logs.
copytruncate trade-offs

copytruncate can lose log lines under load and can break log integrity for auditing. Use it only when signaling/reload is not possible.

Rotations not happening

Common causes:

  • Scheduler not running (cron disabled, timer not active)
  • Wrong file path glob
  • notifempty prevents rotation because file is empty
  • logrotate state file indicates it already rotated recently

Validate:

sudo logrotate -d /etc/logrotate.conf
sudo logrotate -d /etc/logrotate.d/<service>

Security notes

  • Logs can contain secrets (session IDs, tokens, query strings). Restrict permissions and retention accordingly.
  • Ensure rotated logs inherit appropriate permissions (create), and do not become world-readable.
  • Consider encrypted off-host backups for compliance, but keep local retention bounded to reduce exposure.
Sensitive data

If logs include authentication headers, personal data, or tokens, reduce retention and restrict access (file permissions and group membership).

Quick reference

TaskCommand
--
Dry run (no changes)sudo logrotate -d /etc/logrotate.conf
Verbose runsudo logrotate -v /etc/logrotate.conf
Force rotationsudo logrotate -f /etc/logrotate.conf
View global configsudo sed -n '1,200p' /etc/logrotate.conf
List per-service configssudo ls -la /etc/logrotate.d/
Check scheduler (systemd)systemctl status logrotate.timer
Check state filesudo tail -n 50 /var/lib/logrotate/status